package engine;

import java.io.File;
import java.io.FileWriter;
import java.io.Serializable;

/**
 * Classe que implementa Heaps binários 
 * @author Vinícius Souza
 * @version 1.0
 */
public class Heap implements Serializable {
	
	private static final long serialVersionUID = 1L;
	private int[] arrayValues;
	
	/**
	 * Construtor da classe
	 * @param int[] - valores do heap
	 */
	public Heap(int[] values) {
		arrayValues = values;
	}
	
	/**
	 * Retorna um array com os valores
	 * @return int[] - valores.
	 */
	public int[] getValues() {
		return arrayValues;
	}
	
	/**
	 * Verifica se os valores estão na posição correta
	 * @return boolean - retorna <i>true</i> se houverem valores para serem reposicionados,
	 * do contrário retorna <i>false</i>.
	 */
	public boolean check() {
		for (int i = arrayValues.length-1; i >0; i--) { 
			if (arrayValues[i] < arrayValues[i/2]) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Retorna a posição de um elemento a ser trocado,
	 * Caso nenhum elemento precise ser trocado de posição, retornará -1.
	 * @return int - posição
	 */
	public int getValue() {
		for (int i = arrayValues.length-1; i >0; i--) { 
			if (arrayValues[i] < arrayValues[i/2]) {
				return i;
			} 
		}
		return -1; 
	}
	
	/**
	 * Troca a posição do elemento na posição n <b>n</b> com seu superior 
	 * @param n - posição
	 */
	public void replace() {
		int n = getValue();
		if (check() && (n>(-1))) {				
			int little = arrayValues[n];			
			int big = arrayValues[n/2];			
			arrayValues[n] = big;
			arrayValues[n/2] = little;
		}
	}
	
	/**
	 * Retorna posição relativa a altura do elemento.
	 * @param int - indice
	 * @return int - altura
	 */
	public int getLine(int n) {
		if (n<2) {
			return 1;
		} else if (n<4) {
			return 2;
		} else if (n<8) {
			return 3;
		} else if (n<16) {
			return 4;
		} else if (n<32) {
			return 5;
		} 
		return 6;
	}
	
	/**
	 * Retorna a altura da árvore.
	 * @return int - altura
	 */
	public int getLines() {
		int numeroDeElementos = arrayValues.length;
		if (numeroDeElementos<2) {
			return 1;
		} else if (numeroDeElementos<4) {
			return 2;
		} else if (numeroDeElementos<8) {
			return 3;
		} else if (numeroDeElementos<16) {
			return 4;
		} else if (numeroDeElementos<32) {
			return 5;
		} 
		return 6;
	}
	
	/**
	 * Retorna uma string com o texto a ser escrito no arquivo que representa o grafo.
	 * @return String - texto
	 */
	public String getGraphvizText() {
		String string = "graph HeapSort {\n";
		for (int i = arrayValues.length-1; i>=0; i--) {
			string += String.format("%d -- %d;\n", arrayValues[i], arrayValues[i/2]) ;
		}
		return string + "}\n";
	}
	
	/**
	 * Gera um arquivo de texto que representa o grafo e pode ser interpretado pelo graphviz.
	 */
	public void saveFile() {
		try {
			File arquivo = new File("HeapSort1.txt");
			FileWriter saida1 = new FileWriter(arquivo);
			saida1.write(getGraphvizText());
			saida1.close();
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
	}
		
	@Override
	public String toString() {
		return getGraphvizText().trim();
	}
}
